/******************************************************************************/
/*! 
    Filename
    [Copyright]

    \file
    \namespace    
    \brief
*/
/******************************************************************************/
/*** Include guard ************************************************************/
#ifndef RTTI_H
#define RTTI_H

/*** Includes *****************************************************************/
#include <string>

/*** Forward Declarations *****************************************************/

/*** Namespace ****************************************************************/
namespace Core
{
/*** Macros *******************************************************************/

/*** Constants ****************************************************************/ 

/*** Interface ****************************************************************/
class NRtti
{
public:
	virtual const unsigned int& TypeIdInstance() const = 0;
		
	virtual NRtti* QueryInterface(const unsigned) const
	{
		return NULL;
	}

	virtual bool Is(const unsigned int) const
	{
		return false;
	}

	virtual bool Is(const char*) const
	{
		return false;
	}

	template <typename T>
    T* As() const
    {
		if (Is(T::TypeIdClass()))
		{
			return (T*)this;
		}
		return NULL;
    }
};

#define RTTI_DECLARATIONS(Type, ParentType)                                                              \
	private:                                                                                             \
		static unsigned int sRunTimeTypeId;                                                              \
	public:                                                                                              \
		typedef ParentType Parent;                                                                       \
		static std::string TypeName() { return std::string(#Type); }									 \
		virtual const unsigned int& TypeIdInstance() const { return Type::TypeIdClass(); }               \
		static  const unsigned int& TypeIdClass() { return sRunTimeTypeId; }                             \
		virtual Core::NRtti* QueryInterface( const unsigned int id ) const                               \
        {                                                                                                \
            if (id == sRunTimeTypeId)                                                                    \
				{ return (NRtti*)this; }                                                                 \
            else                                                                                         \
				{ return Parent::QueryInterface(id); }                                                   \
        }                                                                                                \
		virtual bool Is(const unsigned int id) const                                                     \
		{                                                                                                \
			if (id == sRunTimeTypeId)                                                                    \
				{ return true; }                                                                         \
			else                                                                                         \
				{ return Parent::Is(id); }                                                               \
		}                                                                                                \
		virtual bool Is(const char*  name) const                                                         \
		{                                                                                                \
			if ( TypeName() == name)                                                                     \
				{ return true; }                                                                         \
			else                                                                                         \
				{ return Parent::Is(name); }                                                             \
		}
			
#define RTTI_DEFINITIONS(Type) unsigned int Type::sRunTimeTypeId = (unsigned int)& Type::sRunTimeTypeId;
}
#endif //RTTI_H